#include "Common.h"

Common::Common()
{
	// Empty
}

Common::~Common()
{
	// Empty
}

bool Common::SetClipboardData(const String& string)
{
	HGLOBAL GlobalString;
	c8* GlobalStringPointer;

	if(!::OpenClipboard(NULL))
	{
		Error::Instance().SetMessage("Unable to open the clipboard!");
		return false;
	}

	GlobalString = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (u32)(string.size()) + 1);
	if(GlobalString == NULL)
	{
		::CloseClipboard();
		Error::Instance().SetMessage("Unable to allocate memory for the clipboard data!");
		return false;
	}

	EmptyClipboard();

	GlobalStringPointer = reinterpret_cast<c8*>(::GlobalLock(GlobalString));
	if(GlobalStringPointer == NULL)
	{
		::CloseClipboard();
		Error::Instance().SetMessage("Unable to lock the global memory!");
		return false;
	}

	std::memcpy(GlobalStringPointer, string.c_str(), (u32)(string.size()) + 1);
	::GlobalUnlock(GlobalString);

	::SetClipboardData(CF_TEXT, GlobalString);
	::CloseClipboard();

	return true;
}

String Common::GetClipboardData()
{
	u32 size;
	HGLOBAL globalString;
	c8* globalStringPointer;
	std::vector<c8> buffer;

	if(!::OpenClipboard(NULL)) return "";

	globalString = ::GetClipboardData(CF_TEXT);
	if(globalString == NULL)
	{
		::CloseClipboard();
		return "";
	}

	globalStringPointer = reinterpret_cast<c8*>(::GlobalLock(globalString));
	if(globalStringPointer == NULL)
	{
		::CloseClipboard();
		return "";
	}

	size = (u32)(std::strlen(globalStringPointer));
	buffer.resize(size + 1);
	std::memcpy(&buffer[0], globalStringPointer, size);
	buffer[size] = '\0';

	::GlobalUnlock(globalString);
	::CloseClipboard();

	return &buffer[0];
}

String Common::LowerCase(const String& string) const
{
	String result = string;

	for(u32 i = 0; i < (u32)(result.size()); i++)
	{
		result[i] = std::tolower(result[i]);
	}

	return result;
}

String Common::UpperCase(const String& string) const
{
	String result = string;

	for(u32 i = 0; i < (u32)(result.size()); i++)
	{
		result[i] = std::toupper(result[i]);
	}

	return result;
}

String Common::GetPath(const String& fileName) const
{
	u32 i;

	i = (u32)(fileName.rfind("\\"));
	if(i == String::npos)
	{
		i = (u32)(fileName.rfind("/"));
		if(i == String::npos)
		{
			return "";
		}
	}

	return fileName.substr(0, i + 1);
}

String Common::GetName(const String& fileName) const
{
	u32 i;
	u32 j;

	i = (u32)(fileName.rfind("\\"));
	if(i == String::npos)
	{
		i = (u32)(fileName.rfind("/"));
		if(i == String::npos)
		{
			i = -1;
		}
	}

	j = (u32)(fileName.rfind("."));
	if(j == String::npos) j = (u32)(fileName.size());

	return fileName.substr(i + 1, j - i - 1);
}

String Common::GetFileName(const String& fileName) const
{
	u32 i;

	i = (u32)(fileName.rfind("\\"));
	if(i == String::npos)
	{
		i = (u32)(fileName.rfind("/"));
		if(i == String::npos)
		{
			return fileName;
		}
	}

	return fileName.substr(i + 1, fileName.size() - i - 1);
}

String Common::GetExtention(const String& fileName) const
{
	u32 i;

	i = (u32)(fileName.rfind("."));
	if(i == String::npos) return "";

	return fileName.substr(i + 1, fileName.size() - i - 1);
}

void Common::SplitFileName(String& fullFileName, String& path, String& name, String& fileName, String& extention) const
{
	u32 i;
	u32 j;

	i = (u32)(fullFileName.rfind("\\"));
	if(i == String::npos)
	{
		i = (u32)(fullFileName.rfind("/"));
		if(i == String::npos)
		{
			i = -1;
		}
	}

	j = (u32)(fullFileName.rfind("."));
	if(j == String::npos) j = (u32)(fullFileName.size());

	path = (i >= 0) ? fullFileName.substr(0, i + 1) : "";
	name = fullFileName.substr(i + 1, j - i - 1);
	fileName = fullFileName.substr(i + 1, fullFileName.size() - i - 1);
	extention = (j < (u32)(fullFileName.size())) ? fullFileName.substr(i + 1, fullFileName.size() - i - 1) : "";
}

String Common::GetProgramFileName() const
{
	u32 i;
	String fileName;
	c8 buffer[BUFFER_SIZE];

	::GetModuleFileName(NULL, buffer, BUFFER_SIZE - 1);
	fileName = buffer;

	i = (u32)(fileName.rfind("\\"));
	if(i != String::npos)
	{
		fileName = fileName.substr((i + 1), ((u32)(fileName.size()) - (i + 1)));
	}

	return fileName;
}

String Common::GetProgramDirectory() const
{
	u32 i;
	String directory;
	c8 buffer[BUFFER_SIZE];

	::GetModuleFileName(NULL, buffer, BUFFER_SIZE - 1);
	directory = buffer;

	i = (u32)(directory.rfind("\\"));
	if(i != String::npos)
	{
		directory = directory.substr(0, i);
	}

	return directory;
}

String Common::GetCurrentDirectory() const
{
	c8 buffer[BUFFER_SIZE];

	if(::GetCurrentDirectory(BUFFER_SIZE - 1, buffer) == 0) return "";

	return buffer;
}

void Common::SetCurrentDirectory(const String& newDir) const
{
	::SetCurrentDirectory(newDir.c_str());
}

bool Common::IsWhiteSpace(c8 Char) const
{
	if(Char == ' ')  return true;
	if(Char == '\t') return true;
	if(Char == '\n') return true;
	if(Char == '\r') return true;

	return false;
}

bool Common::IsLineBreak(c8 Char) const
{
	if(Char == '\n') return true;
	if(Char == '\r') return true;

	return false;
}

bool Common::IsDigit(c8 Char) const
{
	return (Char >= '0') && (Char <= '9');
}

bool Common::IsLetter(c8 Char) const
{
	if((Char >= 'a') && (Char <= 'z')) return true;
	if((Char >= 'A') && (Char <= 'Z')) return true;

	return false;
}

bool Common::IsLowerCaseLetter(c8 Char) const
{
	return (Char >= 'a') && (Char <= 'z');
}

bool Common::IsUpperCaseLetter(c8 Char) const
{
	return (Char >= 'A') && (Char <= 'Z');
}

void Common::RemoveWhiteSpace(String& string) const
{
	while(string.size() > 0)
	{
		if(!IsWhiteSpace(string[0])) break;
		string.erase(0, 1);
	}

	while(string.size() > 0)
	{
		if(!IsWhiteSpace(string[string.size() - 1])) break;
		string.erase(string.size() - 1, 1);
	}
}

bool Common::StringToBool(const String& string) const
{
	return (LowerCase(string) == "true");
}

s32 Common::StringToInt(const String& string) const
{
	s32 Int = 0;
	std::stringstream Stream(string);

	Stream >> Int;

	return Int;
}

f32 Common::StringToFloat(const String& string) const
{
	f32 Float = 0.0f;
	std::stringstream Stream(string);

	Stream >> Float;

	return Float;
}

String Common::BoolToString(bool Bool) const
{
	return Bool ? "true" : "false";
}

String Common::IntToString(s32 Int) const
{
	std::stringstream Stream;

	Stream << Int;

	return Stream.str();
}

String Common::FloatToString(f32 Float) const
{
	std::stringstream Stream;

	Stream << Float;

	return Stream.str();
}

String Common::GetCurrentDate()
{
	u32 Size;
	u32 Locale;
	String Date;
	String Time;
	std::vector<c8> Buffer;

	Locale = MAKELCID(CURRENT_LANGUAGE, SORT_DEFAULT);

	Size = GetDateFormat(Locale, 0, NULL, STRING_DATE_FORMAT.c_str(), NULL, 0);
	Buffer.resize(Size + 1);

	GetDateFormat(Locale, 0, NULL, STRING_DATE_FORMAT.c_str(), &Buffer[0], Size);
	Buffer[Size] = '\0';
	Date = &Buffer[0];

	Size = GetTimeFormat(Locale, 0, NULL, STRING_TIME_FORMAT.c_str(), NULL, 0);
	Buffer.resize(Size + 1);

	GetTimeFormat(Locale, 0, NULL, STRING_TIME_FORMAT.c_str(), &Buffer[0], Size);
	Buffer[Size] = '\0';
	Time = &Buffer[0];

	return Date + " " + Time;
}
